///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_MAT_DETAIL_GENERATORS_H_
#define _BUOLA_MAT_DETAIL_GENERATORS_H_

#include <buola/utility/random.h>

namespace buola { namespace mat { namespace detail {

struct COnesGenerator
{
    template<typename tScalar>
    tScalar Get() const
    {
        return (tScalar)1;
    }
};

struct CZerosGenerator
{
    template<typename tScalar>
    tScalar Get() const
    {
        return (tScalar)0;
    }
};

template<typename tConstant>
struct CConstantGenerator
{
    CConstantGenerator(tConstant pConstant)
        :   mConstant(pConstant)
    {}
    
    template<typename tScalar>
    tScalar Get() const
    {
        static_assert(std::is_same<tScalar,tConstant>::value,"type of constant must match type of expression");
        return mConstant;
    }

private:
    tConstant mConstant;
};

template<typename tDistribution>
class CRandomGenerator
{
    typedef typename tDistribution::result_type TScalar;

public:
    CRandomGenerator(const tDistribution &pDistribution)
        :   mGenerator(random::engine(),pDistribution)
    {}

    template<typename tScalar>
    tScalar Get() const
    {
        static_assert(std::is_same<tScalar,TScalar>::value,"wrong type in CRandomGenerator");
        return mGenerator();
    }

private:
    mutable random::CGenerator<random::CDefaultEngine,tDistribution> mGenerator;
};
    
/*namespace detail*/ } /*namespace mat*/ } /*namespace buola*/ }

#endif
